package ru.spb.osll.myfit.server.templateloader;

import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Vector;

import org.apache.log4j.Logger;
import ru.spb.osll.myfit.server.fixtureiterator.ClasspathIterator;
import ru.spb.osll.myfit.server.fixtureiterator.FileFactory;
import ru.spb.osll.myfit.server.fixtureiterator.FixtureIteratorListener;

public abstract class BaseTableTemplateLoader implements TableTemplateLoader {
  private static Logger log = Logger.getLogger(BaseTableTemplateLoader.class);
  protected abstract URLClassLoader getClassLoader();

  protected abstract URL[] getFixturesUrls();

  public Map<String, Class<?>> getFixtureClasses() {
    final HashMap<String, Class<?>> res = new HashMap<String, Class<?>>();

    FixtureIteratorListener listener = new FixtureIteratorListener() {
      public void listen(Class<?> clazz) {
        res.put(clazz.getSimpleName(), clazz);
      }
    };

    ClasspathIterator iterator = new ClasspathIterator(getClassLoader(), new FileFactory(), getFixturesUrls());
    iterator.iterateFixtures(listener);

    return res;
  }

  public Vector<String> getTemplate(String name) {
    Vector<String> rawTable = new Vector<String>();
    Class<?> clazz = null;
    try {
      clazz = getClassLoader().loadClass(name);
      rawTable = getTemplate(clazz);
    } catch (Exception e) {
      log.error(e);
    }

    return rawTable;
  }

  private Vector<String> getTemplate(Class<?> clazz) {
    Vector<String> rawTable = new Vector<String>();
    try {
      Method getTestTableTemplatesMethod = clazz.getMethod("getTestTableTemplates");

      String[] templates = (String[]) getTestTableTemplatesMethod.invoke(null);
      BufferedReader inStream = new BufferedReader(new StringReader(
              templates[0]));
      String line = null;
      while ((line = inStream.readLine()) != null) {
        if (line.matches("|.*|"))
          rawTable.add(line);
      }

    } catch (NoSuchMethodException e) {
      log.warn(e.getMessage());
    } catch (Exception e) {
      log.error(e);
    }

    return rawTable;
  }

  protected LinkedList<URL> getJars(String directoryPath) {
    File dir = new File(directoryPath);
    String[] jars = dir.list(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        return name.endsWith(".jar");
      }
    });

    LinkedList<URL> urls = new LinkedList<URL>();
    for (String jar : jars) {
      try {
        urls.add(new URL("file", "localhost", directoryPath + File.separator + jar));
      } catch (MalformedURLException e) {
        e.printStackTrace();
      }
    }

    return urls;
  }
}
